home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / 295_01.zip / BOPS.C < prev    next >
Text File  |  1993-04-22  |  14KB  |  593 lines

  1. /*    Copyright (c) 1989 Citadel    */
  2. /*       All Rights Reserved        */
  3.  
  4. /* #ident    "bops.c    1.2 - 89/10/31" */
  5.  
  6. #include <bool.h>
  7. #include <errno.h>
  8. /*#include <stddef.h>*/
  9. /*#include <stdlib.h>*/
  10. /*#include <string.h>*/
  11. #include "blkio_.h"
  12.  
  13. /*man---------------------------------------------------------------------------
  14. NAME
  15.      b_alloc - allocate memory for block file
  16.  
  17. SYNOPSIS
  18.      #include "blkio_.h"
  19.  
  20.      int b_alloc(bp)
  21.      BLKFILE *bp;
  22.  
  23. DESCRIPTION
  24.      The b_alloc function allocates the memory needed by bp.  The
  25.      memory is initialized to all zeros.  A call to b_alloc should
  26.      normally be followed by a call to b_initlist to construct the
  27.      linked list for LRU replacement.
  28.  
  29.      b_alloc will fail if one or more of the following is true:
  30.  
  31.      [EINVAL]       bp is not a valid BLKFILE pointer.
  32.      [ENOMEM]       Enough memory is not available for
  33.                     allocation by the calling process.
  34.      [BENOPEN]      bp is not open.
  35.  
  36. SEE ALSO
  37.      b_free, b_initlist.
  38.  
  39. DIAGNOSTICS
  40.      Upon successful completion, a value of 0 is returned.  Otherwise,
  41.      a value of -1 is returned, and errno set to indicate the error.
  42.  
  43. ------------------------------------------------------------------------------*/
  44. int b_alloc(bp)
  45. BLKFILE *bp;
  46. {
  47. #ifdef DEBUG
  48.     /* validate arguments */
  49.     if (!b_valid(bp)) {
  50.         BEPRINT;
  51.         errno = EINVAL;
  52.         return -1;
  53.     }
  54.  
  55.     /* check if not open */
  56.     if (!(bp->flags & BIOOPEN)) {
  57.         BEPRINT;
  58.         errno = BENOPEN;
  59.         return -1;
  60.     }
  61.  
  62.     /* check for memory leak */
  63.     if ((bp->block_p != NULL) || ((bp->blkbuf != NULL) && !(bp->flags & BIOUSRBUF))) {
  64.         BEPRINT;
  65.         errno = BEPANIC;
  66.         return -1;
  67.     }
  68. #endif
  69.  
  70.     /* check if not buffered */
  71.     if (bp->bufcnt == 0) {
  72.         errno = 0;
  73.         return 0;
  74.     }
  75.  
  76.     /* allocate buffer storage (one extra block structure for header) */
  77.     bp->block_p = (block_t *)calloc(bp->bufcnt + 1, sizeof(block_t));
  78.     if (bp->block_p == NULL) {
  79.         BEPRINT;
  80.         errno = ENOMEM;
  81.         return -1;
  82.     }
  83.     if (!(bp->flags & BIOUSRBUF)) {
  84.         bp->blkbuf = calloc((size_t)1, bp->hdrsize + bp->bufcnt * bp->blksize);
  85.         if (bp->blkbuf == NULL) {
  86.             BEPRINT;
  87.             free(bp->block_p);
  88.             bp->block_p = NULL;
  89.             errno = ENOMEM;
  90.             return -1;
  91.         }
  92.     }
  93.  
  94.     errno = 0;
  95.     return 0;
  96. }
  97.  
  98. /*man---------------------------------------------------------------------------
  99. NAME
  100.      b_block_p - pointer to block structure
  101.  
  102. SYNOPSIS
  103.      #include "blkio_.h"
  104.  
  105.      block_t *b_block_p(bp, i)
  106.      BLKFILE *bp;
  107.      size_t i;
  108.  
  109. DESCRIPTION
  110.      b_block_p returns a pointer to the ith block structure in the
  111.      buffer list of block file bp.  If bp is not a valid open block
  112.      file or i is not in the range [0..bp->bufcnt] the results are
  113.      undefined.  b_block_p is a macro.
  114.  
  115. ------------------------------------------------------------------------------*/
  116. /* b_block_p is defined in blkio_.h */
  117.  
  118. /*man---------------------------------------------------------------------------
  119. NAME
  120.      b_blkbuf - pointer to block buffer
  121.  
  122. SYNOPSIS
  123.      #include "blkio_.h"
  124.  
  125.      void *b_blkbuf(bp, i)
  126.      BLKFILE *bp;
  127.      size_t i;
  128.  
  129. DESCRIPTION
  130.      b_blkbuf returns a pointer to the ith buffer in the buffer list
  131.      of block file bp.  A value of zero for i indicates the header
  132.      buffer.  If bp is not a valid BLKFILE pointer to an open file or
  133.      i is not in the range [0..bp->bufcnt] the results are undefined.
  134.      b_blkbuf is a macro.
  135.  
  136. ------------------------------------------------------------------------------*/
  137. /* b_blkbuf is defined in blkio_.h */
  138.  
  139. /*man---------------------------------------------------------------------------
  140. NAME
  141.      b_free - free memory allocated for block file
  142.  
  143. SYNOPSIS
  144.      #include "blkio_.h"
  145.  
  146.      void b_free(bp)
  147.      BLKFILE *bp;
  148.  
  149. DESCRIPTION
  150.      The b_free function frees all memory allocated for block file bp.
  151.      If bp has a user-supplied buffer storage area, it is disconnected
  152.      from bp but is not freed.  On return from b_free, bp->block_p and
  153.      bp->blkbuf will be NULL.
  154.  
  155. SEE ALSO
  156.      b_alloc.
  157.  
  158. ------------------------------------------------------------------------------*/
  159. void b_free(bp)
  160. BLKFILE *bp;
  161. {
  162. #ifdef DEBUG
  163.     /* validate arguments */
  164.     if (!b_valid(bp)) {
  165.         BEPRINT;
  166.         return;
  167.     }
  168. #endif
  169.  
  170.     /* free memory */
  171.     if (!(bp->flags & BIOUSRBUF)) {        /* if not user-supplied buf */
  172.         if (bp->blkbuf != NULL) {        /* free buffer */
  173.             free(bp->blkbuf);
  174.         }
  175.     }
  176.     bp->blkbuf = NULL;            /* disconnect buffer */
  177.     if (bp->block_p != NULL) {
  178.         free(bp->block_p);
  179.         bp->block_p = NULL;
  180.     }
  181.  
  182.     return;
  183. }
  184.  
  185. /*man---------------------------------------------------------------------------
  186. NAME
  187.      b_get - get block from block file
  188.  
  189. SYNOPSIS
  190.      #include "blkio_.h"
  191.  
  192.      int b_get(bp, i)
  193.      BLKFILE *bp;
  194.      size_t i;
  195.  
  196. DESCRIPTION
  197.      The b_get function reads a block from block file bp into the ith
  198.      buffer for that block file.  b_get reads the block identified by
  199.      the block number field of the block structure associated with
  200.      buffer i (i.e., b_block_p(bp, i)->bn); the zeroth buffer is
  201.      always used for the header.  The read flag is set and all others
  202.      cleared for buffer i.
  203.  
  204.      b_get will fail if one or more of the following is true:
  205.  
  206.      [EINVAL]       bp is not a valid BLKFILE pointer.
  207.      [EINVAL]       i is not in the range [0..bp->bufcnt].
  208.      [BEEOF]        End of file occured before end of block.
  209.      [BENBUF]       bp is not buffered.
  210.  
  211. SEE ALSO
  212.      b_put.
  213.  
  214. DIAGNOSTICS
  215.      Upon successful completion, a value of 0 is returned.  Otherwise,
  216.      a value of -1 is returned, and errno set to indicate the error.
  217.  
  218. ------------------------------------------------------------------------------*/
  219. int b_get(bp, i)
  220. BLKFILE *bp;
  221. size_t i;
  222. {
  223. #ifdef DEBUG
  224.     /* validate arguments */
  225.     if (!b_valid(bp)) {
  226.         BEPRINT;
  227.         errno = EINVAL;
  228.         return -1;
  229.     }
  230.  
  231.     /* check if not open */
  232.     if (!(bp->flags & BIOOPEN)) {
  233.         BEPRINT;
  234.         errno = BENOPEN;
  235.         return -1;
  236.     }
  237.  
  238.     /* check if file is not buffered */
  239.     if (bp->bufcnt == 0) {
  240.         BEPRINT;
  241.         errno = BENBUF;
  242.         return -1;
  243.     }
  244.  
  245.     /* validate arguments */
  246.     if ((i > bp->bufcnt)) {
  247.         BEPRINT;
  248.         errno = EINVAL;
  249.         return -1;
  250.     }
  251.  
  252.     /* check if block number set */
  253.     if ((b_block_p(bp, i)->bn == 0) && (i != 0)) {
  254.         BEPRINT;
  255.         errno = BEPANIC;
  256.         return -1;
  257.     }
  258.  
  259.     /* check if block needs to be written to disk */
  260.     if (b_block_p(bp, i)->flags & BLKWRITE) {
  261.         BEPRINT;
  262.         errno = BEPANIC;
  263.         return -1;
  264.     }
  265. #endif
  266.  
  267.     /* read block from file */
  268.     if (i == 0) {
  269.         if (b_ugetf(bp, (bpos_t)0, (size_t)0, b_blkbuf(bp, (size_t)0), bp->hdrsize) == -1) {
  270.             BEPRINT;
  271.             return -1;
  272.         }
  273.     } else {
  274.         if (b_ugetf(bp, b_block_p(bp, i)->bn, (size_t)0, b_blkbuf(bp, i), bp->blksize) == -1) {
  275.             BEPRINT;
  276.             return -1;
  277.         }
  278.     }
  279.  
  280.     /* set read flag and clear all others */
  281.     b_block_p(bp, i)->flags = BLKREAD;
  282.  
  283.     errno = 0;
  284.     return 0;
  285. }
  286.  
  287. /*man---------------------------------------------------------------------------
  288. NAME
  289.      b_initlist - build linked list
  290.  
  291. SYNOPSIS
  292.      #include "blkio_.h"
  293.  
  294.      int b_initlist(bp)
  295.      BLKFILE *bp;
  296.  
  297. DESCRIPTION
  298.      The b_initlist function builds the linked list of buffers for
  299.      block file bp.  The buffer contents are deleted in the process.
  300.      A call to b_initlist should normally follow a call to b_alloc.
  301.  
  302.      b_initlist will fail if one or more of the following is true:
  303.  
  304.      [EINVAL]       bp is not a valid block file.
  305.  
  306. SEE ALSO
  307.      b_alloc.
  308.  
  309. DIAGNOSTICS
  310.      Upon successful completion, a value of 0 is returned.  Otherwise,
  311.      a value of -1 is returned, and errno set to indicate the error.
  312.  
  313. ------------------------------------------------------------------------------*/
  314. int b_initlist(bp)
  315. BLKFILE *bp;
  316. {
  317.     size_t i = 0;
  318.  
  319. #ifdef DEBUG
  320.     /* validate arguments */
  321.     if (!b_valid(bp)) {
  322.         BEPRINT;
  323.         errno = EINVAL;
  324.         return -1;
  325.     }
  326.  
  327.     /* check if not open */
  328.     if (!(bp->flags & BIOOPEN)) {
  329.         BEPRINT;
  330.         errno = BENOPEN;
  331.         return -1;
  332.     }
  333. #endif
  334.  
  335.     /* initialize head and tail of list */
  336.     bp->most = 0;
  337.     bp->least = 0;
  338.  
  339.     /* check if not buffered */
  340.     if (bp->bufcnt == 0) {
  341.         errno = 0;
  342.         return 0;
  343.     }
  344.  
  345.     /* initialize linked list */
  346.     bp->most = bp->bufcnt;
  347.     bp->least = 1;
  348.     for (i = 1; i <= bp->bufcnt; i++) {
  349.         b_block_p(bp, i)->bn = 0;
  350.         b_block_p(bp, i)->flags = 0;
  351.         b_block_p(bp, i)->more = i + 1;
  352.         b_block_p(bp, i)->less = i - 1;
  353.     }
  354.     b_block_p(bp, bp->most)->more = 0;
  355.     b_block_p(bp, bp->least)->less = 0;
  356.  
  357.     /* initialize block structure for header */
  358.     b_block_p(bp, (size_t)0)->bn = 0;
  359.     b_block_p(bp, (size_t)0)->flags = 0;
  360.     b_block_p(bp, (size_t)0)->more = 0;
  361.     b_block_p(bp, (size_t)0)->less = 0;
  362.  
  363.     /* scrub buffer storage area */
  364.     memset(bp->blkbuf, 0, bp->hdrsize + bp->bufcnt * bp->blksize);
  365.  
  366.     errno = 0;
  367.     return 0;
  368. }
  369.  
  370. /*man---------------------------------------------------------------------------
  371. NAME
  372.      b_mkmru - make most recently used block
  373.  
  374. SYNOPSIS
  375.      #include "blkio_.h"
  376.  
  377.      int b_mkmru(bp, i)
  378.      BLKFILE *bp;
  379.      size_t i;
  380.  
  381. DESCRIPTION
  382.      The b_mkmru function moves the ith block in the buffer list to
  383.      the most recently used end of the buffer list.
  384.  
  385.      b_mkmru will fail if one or more of the following is true:
  386.  
  387.      [EINVAL]       bp is not a valid block file.
  388.      [EINVAL]       i is not in the range [1..bp->bufcnt].
  389.      [BENBUF]       bp is not buffered.
  390.  
  391. DIAGNOSTICS
  392.      Upon successful completion, a value of 0 is returned.  Otherwise,
  393.      a value of -1 is returned, and errno set to indicate the error.
  394.  
  395. ------------------------------------------------------------------------------*/
  396. int b_mkmru(bp, i)
  397. BLKFILE *bp;
  398. size_t   i;
  399. {
  400.     size_t more = 0;
  401.     size_t less = 0;
  402.  
  403. #ifdef DEBUG
  404.     /* validate arguments */
  405.     if (!b_valid(bp)) {
  406.         BEPRINT;
  407.         errno = EINVAL;
  408.         return -1;
  409.     }
  410.  
  411.     /* check if not open */
  412.     if (!(bp->flags & BIOOPEN)) {
  413.         BEPRINT;
  414.         errno = BENOPEN;
  415.         return -1;
  416.     }
  417.  
  418.     /* check if file is not buffered */
  419.     if (bp->bufcnt == 0) {
  420.         BEPRINT;
  421.         errno = BENBUF;
  422.         return -1;
  423.     }
  424.  
  425.     /* validate arguments */
  426.     if ((i < 1) || (i > bp->bufcnt)) {
  427.         BEPRINT;
  428.         errno = EINVAL;
  429.         return -1;
  430.     }
  431. #endif
  432.  
  433.     /* check block addresses */
  434.     more = b_block_p(bp, i)->more;
  435.     less = b_block_p(bp, i)->less;
  436.     if ((more > bp->bufcnt) || (less > bp->bufcnt)) {
  437.         BEPRINT;
  438.         errno = BEPANIC;
  439.         return -1;
  440.     }
  441.  
  442.     /* check if already most recently used */
  443.     if (more == 0) {
  444.         errno = 0;
  445.         return 0;
  446.     }
  447.  
  448.     /* remove block i from linked list */
  449.     b_block_p(bp, more)->less = less;
  450.     if (less != 0) {
  451.         b_block_p(bp, less)->more = more;
  452.     } else {
  453.         bp->least = more;
  454.     }
  455.  
  456.     /* connect ith block as most recently used */
  457.     b_block_p(bp, i)->more = 0;
  458.     b_block_p(bp, i)->less = bp->most;
  459.     b_block_p(bp, bp->most)->more = i;
  460.     bp->most = i;
  461.  
  462.     errno = 0;
  463.     return 0;
  464. }
  465.  
  466. /*man---------------------------------------------------------------------------
  467. NAME
  468.      b_put - put block into block file
  469.  
  470. SYNOPSIS
  471.      #include "blkio_.h"
  472.  
  473.      int b_put(bp, i)
  474.      BLKFILE *bp;
  475.      size_t i;
  476.  
  477. DESCRIPTION
  478.      The b_put function writes a block from the ith buffer of block
  479.      file bp to the file.  b_put writes to the block identified by
  480.      the block number field of the block structure associated with
  481.      buffer i (i.e., b_block_p(bp, i)->bn); the zeroth buffer is
  482.      always used for the header.  If the write flag is not set,
  483.      nothing is written.  After writing, the write flag is cleared.
  484.  
  485.      b_put will fail if one or more of the following is true:
  486.  
  487.      [EINVAL]       bp is not a valid block file.
  488.      [EINVAL]       i is not in the range [0..bp->bufcnt].
  489.      [BENBUF]       bp is not buffered.
  490.  
  491. SEE ALSO
  492.      b_get.
  493.  
  494. DIAGNOSTICS
  495.      Upon successful completion, a value of 0 is returned.  Otherwise,
  496.      a value of -1 is returned, and errno set to indicate the error.
  497.  
  498. ------------------------------------------------------------------------------*/
  499. int b_put(bp, i)
  500. BLKFILE *bp;
  501. size_t i;
  502. {
  503. #ifdef DEBUG
  504.     /* validate arguments */
  505.     if (!b_valid(bp)) {
  506.         BEPRINT;
  507.         errno = EINVAL;
  508.         return -1;
  509.     }
  510.  
  511.     /* check if not open */
  512.     if (!(bp->flags & BIOOPEN)) {
  513.         BEPRINT;
  514.         errno = BENOPEN;
  515.         return -1;
  516.     }
  517.  
  518.     /* check if file is not buffered */
  519.     if (bp->bufcnt == 0) {
  520.         BEPRINT;
  521.         errno = BENBUF;
  522.         return -1;
  523.     }
  524.  
  525.     /* validate arguments */
  526.     if (i > bp->bufcnt) {
  527.         BEPRINT;
  528.         errno = EINVAL;
  529.         return -1;
  530.     }
  531. #endif
  532.  
  533.     /* check if block doesn't need to be written to disk */
  534.     if (!(b_block_p(bp, i)->flags & BLKWRITE)) {
  535.         errno = 0;
  536.         return 0;
  537.     }
  538.  
  539.     /* check for inconsistent read flag setting */
  540.     if (!(b_block_p(bp, i)->flags & BLKREAD)) {
  541.         BEPRINT;
  542.         errno = BEPANIC;
  543.         return 0;
  544.     }
  545.  
  546.     /* write block to disk */
  547.     if (i == 0) {
  548.         if (b_uputf(bp, (bpos_t)0, (size_t)0, b_blkbuf(bp, (size_t)0), bp->hdrsize) == -1) {
  549.             BEPRINT;
  550.             return -1;
  551.         }
  552.     } else {
  553.         if (b_uputf(bp, b_block_p(bp, i)->bn, (size_t)0, b_blkbuf(bp, i), bp->blksize) == -1) {
  554.             BEPRINT;
  555.             return -1;
  556.         }
  557.     }
  558.  
  559.     /* clear all but read flag */
  560.     b_block_p(bp, i)->flags = BLKREAD;
  561.  
  562.     errno = 0;
  563.     return 0;
  564. }
  565.  
  566. /*man---------------------------------------------------------------------------
  567. NAME
  568.      b_valid - validate block file pointer
  569.  
  570. SYNOPSIS
  571.      #include "blkio_.h"
  572.  
  573.      bool b_valid(bp)
  574.      BLKFILE *bp;
  575.  
  576. DESCRIPTION
  577.      The b_valid function determines if bp is a valid BLKFILE pointer.
  578.      If valid, the TRUE is returned.  If not, then FALSE is returned.
  579.  
  580. ------------------------------------------------------------------------------*/
  581. bool b_valid(bp)
  582. CONST BLKFILE *bp;
  583. {
  584.     if ((bp < biob) || (bp > (biob + BOPEN_MAX - 1))) {
  585.         return FALSE;
  586.     }
  587.     if (((char *)bp - (char *)biob) % sizeof(*biob) != 0) {
  588.         return FALSE;
  589.     }
  590.  
  591.     return TRUE;
  592. }
  593.